<template>
    <section class="fav-list-container">
        <h2>{{ title }}</h2>
        <div infinite-wrapper v-on:scroll="onScroll">
            <div v-if="category === 'media'">
                <div v-for="group in groupedMediaItems"
                     :key="group.category"
                     class="media-category-container">
                    <p>{{ group.category }}</p>
                    <ul class="media-category-items">
                        <li v-for="(favItem, index ) in group.items"
                            @contextmenu="openFavContextMenu($event, favItem)"
                            @click="handleClickMedia(index, group.items)"
                            :key="favItem.id">
                            <div v-if="favItem.type === 3" class="media-item-image">
                                <img :src="favItem.url">
                            </div>
                            <div v-else class="media-item-video">
                                <video preload="metadata" :src="favItem.url"/>
                                <i class="icon-ion-play"></i>
                            </div>
                        </li>
                    </ul>
                </div>
            </div>
            <ul v-else>
                <li v-for="(favItem, index) in (filteredFavItems)"
                    @contextmenu="openFavContextMenu($event, favItem)"
                    :key="index">
                    <div class="fav-item-container" @click="handleClick(favItem)">
                        <div class="fav-item-content">
                            <!--            文件-->
                            <div v-if="favItem.type === 5" class="fav-item-file">
                                <img :src="require(`@/assets/images/filetypes/${favItem._fileIconName}`)" alt="">
                                <div class="name-size">
                                    <p class="name">{{ favItem.title }}</p>
                                    <p class="size">{{ favItem._sizeStr }}</p>
                                </div>
                            </div>
                            <!--            图片-->
                            <div v-else-if="favItem.type === 3" class="fav-item-image">
                                <img :src="favItem.url">
                            </div>
                            <!--            视频-->
                            <div v-else-if="favItem.type === 6" class="fav-item-video">
                                <video preload="metadata" :src="favItem.url"/>
                                <i class="icon-ion-play"></i>
                            </div>
                            <!--            语音消息-->
                            <div v-else-if="favItem.type === 2" class="fav-item-audio">
                                <audio preload="auto" controls controlsList="nodownload">
                                    <source :src="appServerAudioUrl(favItem.url)" type="audio/mp4"/>
                                </audio>
                            </div>
                            <!--                            组合消息-->
                            <div v-else-if="favItem.type === 11" class="fav-item-other">
                                <p>
                                    {{ favItem._content }}
                                </p>
                            </div>
                            <!--            其他-->
                            <div v-else class="fav-item-other">
                                <p>
                                    {{ favItem.title }}
                                </p>
                            </div>
                        </div>
                        <div class="fav-item-sender-time">
                            <p class="time">{{ favItem._timeStr }}</p>
                            <p class="sender">{{ $t('fav.from') + ': ' + favItem.origin }}</p>
                        </div>
                    </div>
                </li>
            </ul>
            <infinite-loading :identifier="infiniteId" force-use-infinite-wrapper direction="bottom"
                              @infinite="infiniteHandler">
                <!--            <template slot="spinner">加载中...</template>-->
                <template slot="no-more">{{ $t('fav.no_more') }}</template>
                <template slot="no-results">{{ $t('fav.all_fav_load') }}</template>
            </infinite-loading>
            <vue-context ref="menu" v-slot="{data:favItem}" :close-on-scroll="true" v-on:close="onMenuClose">
                <!--          更多menu item-->
                <li>
                    <a @click.prevent="deleteFav(favItem)">{{ $t('common.delete') }}</a>
                </li>
                <li>
                    <a @click.prevent="forward(favItem)">{{ $t('misc.send_to_friend') }}</a>
                </li>
            </vue-context>
        </div>
    </section>

</template>

<script>
import helper from "../../util/helper";
import MessageContentType from "../../../wfc/messages/messageContentType";
import wfc from "../../../wfc/client/wfc";
import InfiniteLoading from "@imndx/vue-infinite-loading";
import store from "../../../store";
import {ipcRenderer} from "../../../platform";
import FavItem from "../../../wfc/model/favItem";
import {isElectron} from "../../../platform";
import {_reverseToJsLongString} from "../../../wfc/util/longUtil";
import CompositeMessageContent from "../../../wfc/messages/compositeMessageContent";
import Config from "../../../config";
import IpcEventType from "../../../ipcEventType";
import appServerApi from "../../../api/appServerApi";
import {downloadFile} from "../../../platformHelper";

export default {
    name: "FavListView",
    props: {
        category: {
            type: String,
            default: 'all',
            required: false,
        },
    },
    data() {
        return {
            favItems: [],
            imagePlaceHolder: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNcunDhfwAGwgLoe4t2fwAAAABJRU5ErkJggg==',
            infiniteId: +new Date(),
        }
    },
    methods: {
        /**
         *
         * @param category
         * @param cb {function(number, boolean, boolean)}}
         * @return {Promise<void>}
         */
        async loadFavList(category, cb) {
            let startId = this.favItems.length > 0 ? this.favItems[this.favItems.length - 1].id : 0
            let responseData = await appServerApi.getFavList(startId, 20);
            let data = _reverseToJsLongString(responseData, 'messageUid');
            data = JSON.parse(data);
            if (data && data.result) {
                let obj = data.result;
                let items = obj.items;
                let found = false;
                for (let i = 0; i < items.length; i++) {
                    if (category === 'all') {
                        found = true;
                        break;
                    }
                    if (category === 'file' && items[i].type === MessageContentType.File) {
                        found = true;
                        break;
                    }
                    if (category === 'media' && [MessageContentType.Image, MessageContentType.Video].indexOf(items[i].type) >= 0) {
                        found = true;
                        break;
                    }
                    if (category === 'composite' && items[i].type === MessageContentType.Composite_Message) {
                        found = true;
                        break;
                    }
                }
                this._patchFavItem(items);
                this.favItems = this.favItems.concat(items);
                if (obj.hasMore && !found && cb) {
                    this.loadFavList(category, cb);
                    return;
                }
                cb && cb(obj.hasMore);
            } else {
                console.error('loadFavList failed', responseData)
                cb && cb(false)
            }
        },

        _patchFavItem(favItems) {
            favItems.forEach(fi => {
                if (fi.data) {
                    if (fi.type === MessageContentType.Composite_Message) {
                        let favItem = Object.assign(new FavItem(), fi);
                        favItem.favType = fi.type;
                        let message = favItem.toMessage();
                        let compositeContent = message.messageContent;
                        fi._content = fi.title;
                        if (compositeContent instanceof CompositeMessageContent) {
                            for (let i = 0; i < compositeContent.messages.length && i < 2; i++) {
                                fi._content += '\n';
                                fi._content += compositeContent.messages[i].messageContent.digest(compositeContent.messages[i]);
                            }
                        }
                        message.messageContent = compositeContent;

                        fi._message = message;
                    } else {
                        fi.data = JSON.parse(fi.data);
                    }
                }
                fi._timeStr = helper.dateFormat(fi.timestamp);
                if (fi.type === MessageContentType.File) {
                    fi.title = fi.title ? fi.title : 'unname'
                    fi._fileIconName = helper.getFiletypeIcon(fi.title.substring(fi.title.lastIndexOf('.')))
                    fi._sizeStr = helper.humanSize(fi.data.size)
                }
                fi._senderName = wfc.getUserDisplayName(fi.sender);
            });
        },

        infiniteHandler($state) {
            this.loadFavList(this.category, (hasMore) => {
                if (hasMore) {
                    $state.loaded();
                } else {
                    $state.complete();
                }
            });
        },
        handleClick(favItem) {
            switch (favItem.type) {
                case MessageContentType.Text:
                    if (isElectron()) {
                        let hash = window.location.hash;
                        let url = window.location.origin;
                        if (hash) {
                            url = window.location.href.replace(hash, '#/message');
                        } else {
                            url += "/message"
                        }
                        url += "?data=" + wfc.escape(wfc.utf8_to_b64(JSON.stringify(favItem)));
                        ipcRenderer.send(IpcEventType.SHOW_COMPOSITE_MESSAGE_WINDOW, {
                            url: url,
                        });
                    } else {
                        this.$notify({
                            text: '暂不支持预览，请手机端或者 PC 端查看',
                            type: 'info'
                        })
                    }
                    break;
                case MessageContentType.Image:
                case MessageContentType.Video:
                    store.previewMedia(favItem.url, favItem.thumbUrl, favItem.data && favItem.data.thumb ? favItem.data.thumb : 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNcunDhfwAGwgLoe4t2fwAAAABJRU5ErkJggg==')
                    break;
                case MessageContentType.File:
                    let fi = Object.assign(new FavItem(), favItem);
                    downloadFile(fi.toMessage())
                    break;
                case MessageContentType.Composite_Message:
                    if (isElectron()) {
                        let hash = window.location.hash;
                        let url = window.location.origin;
                        if (hash) {
                            url = window.location.href.replace(hash, '#/composite');
                        } else {
                            url += "/composite"
                        }
                        url += "?data=" + wfc.escape(wfc.utf8_to_b64(JSON.stringify(favItem)));
                        ipcRenderer.send(IpcEventType.SHOW_COMPOSITE_MESSAGE_WINDOW, {
                            url: url,
                        });
                    } else {
                        this.$notify({
                            text: '暂不支持预览，请手机端或者 PC 端查看',
                            type: 'info'
                        })
                    }
                    break;
                default:
                    console.log('todo click', favItem)
                    break;
            }
        },
        handleClickMedia(index, favItems) {
            let mediaItems = [];
            favItems = favItems.filter(favItem => (favItem.url || favItem.thumbUrl || (favItem.data && favItem.data.thumb)))
            favItems.forEach(favItem => {
                let thumb = favItem.thumbUrl ? favItem.thumbUrl : (favItem.data && favItem.data.thumb ? 'data:image/png;base64,' + favItem.data.thumb : '')
                mediaItems.push({
                    src: favItem.url,
                    thumb: thumb,
                    autoplay: true,
                })
            })
            store.previewMedias(mediaItems, index)
        },
        openFavContextMenu(event, favItem) {
            if (!favItem) {
                return;
            }
            if (favItem.type === MessageContentType.MESSAGE_CONTENT_TYPE_MIX_MULTI_MEDIA_TEXT) {
                this.$notify({
                    text: '此类型，暂不支持转发',
                    type: 'warn'
                });
                return;
            }
            this.$refs.menu.open(event, favItem);
        },
        onMenuClose() {
            // do nothing
        },

        deleteFav(favItem) {
            appServerApi.delFav(favItem.id)
                .then(response => {
                    this.favItems = this.favItems.filter(fi => fi.id !== favItem.id);
                })
                .catch(err => {
                    console.log('delFav error', err);
                })
        },

        forward(favItem) {
            favItem = Object.assign(new FavItem(), favItem);
            favItem.favType = favItem.type;
            this.$eventBus.$emit('forward-fav', {
                favItem: favItem,
            })
        },
        onScroll() {
            // hide message context menu
            this.$refs.menu && this.$refs.menu.close();
        },

        appServerAudioUrl(url) {
            return Config.AMR_TO_MP3_SERVER_ADDRESS + url;
        }
    },

    computed: {
        title() {
            let str = this.$t('fav.fav');
            switch (this.category) {
                case 'all':
                    str = this.$t('fav.all');
                    break;
                case 'file':
                    str = this.$t('fav.file');
                    break;
                case 'media':
                    str = this.$t('fav.media');
                    break;
                case 'composite':
                    str = this.$t('fav.composite');
                    break;
                default:
                    break;
            }
            return str;
        },
        filteredFavItems() {
            let items = this.favItems;
            switch (this.category) {
                case 'all':
                    items = this.favItems;
                    break;
                case 'file':
                    items = this.favItems.filter(fi => fi.type === MessageContentType.File)
                    break;
                case 'media':
                    items = this.favItems.filter(fi => fi.type === MessageContentType.Image || fi.type === MessageContentType.Video)
                    break;
                case 'composite':
                    items = this.favItems.filter(fi => fi.type === MessageContentType.Composite_Message)
                    break;
                default:
                    break;
            }
            return items;
        },

        groupedMediaItems() {
            let items = this.favItems.filter(fi => fi.type === MessageContentType.Image || fi.type === MessageContentType.Video)
            let groupedItems = [];

            let months = [this.$t('common.month_1'), this.$t('common.month_1'), this.$t('common.month_2'), this.$t('common.month_3'), this.$t('common.month_4'), this.$t('common.month_5'), this.$t('common.month_6'), this.$t('common.month_7'), this.$t('common.month_8'), this.$t('common.month_9'), this.$t('common.month_10'), this.$t('common.month_11'), this.$t('common.month_12'),];

            let map = new Map();
            items.forEach(item => {
                let favDate = new Date(item.timestamp);
                let category = months[favDate.getMonth()] + ' ' + favDate.getFullYear();
                if (!map.has(category)) {
                    map.set(category, [item]);
                } else {
                    map.get(category).push(item);
                }
            });
            groupedItems = Array.from(map).map(([category, items]) => ({category: category, items: items}))

            console.log('groupedItems', groupedItems)
            // groupedItems = groupedItems.concat(groupedItems)
            return groupedItems;
        },
    },

    mounted() {
        // this.loadFavList('all');
    },
    deactivated() {
        this.favItems = [];
    },
    activated() {
        this.infiniteId += 1;
    },
    components: {
        InfiniteLoading,
    }
}
</script>

<style lang="css" scoped>
.fav-list-container {
    height: 100%;
    display: flex;
    flex-direction: column;
}

.fav-list-container h2 {
    width: 100%;
    height: 60px;
    font-size: 16px;
    font-style: normal;
    font-weight: normal;
    display: flex;
    align-items: center;
    padding-left: 20px;
    border-bottom: 1px solid #ebebeb;
}

.fav-list-container div {
    flex: 1;
    overflow: auto;
}

.fav-item-container {
    width: 100%;
    display: flex;
    min-height: 75px;
    max-height: 110px;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    position: relative;
    padding: 0 80px;
}

.fav-item-container:after {
    position: absolute;
    content: " ";
    height: 0;
    left: 80px;
    right: 80px;
    bottom: 0;
    border-bottom: 1px solid #e4e4e4;
}

.fav-item-container:active {
    background-color: #dedede;
}

.fav-item-content {
    flex: 1;
    padding-right: 20px;
    display: flex;
    align-items: center;
}

.fav-item-other p {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    white-space: pre-line;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 12px;
    color: #252525;
}

.fav-item-image {
    height: 110px;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.fav-item-image img {
    height: 70px;
    width: 140px;
    object-fit: cover;
}

.fav-item-file {
    display: flex;
    font-size: 12px;
    height: 110px;
    align-items: center;
}

.fav-item-file img {
    width: 60px;
    height: 60px;
    margin: 0 20px 0 10px;
}

.fav-item-file .name-size {
    padding: 25px 0;
    height: 100%;
    flex: 1;
    max-width: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}

.fav-item-file .name {
    color: #252525;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fav-item-file .size {
    color: #b2b2b2;
}

.fav-item-video {
    height: 110px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    position: relative;
}

.fav-item-video video {
    background-color: lightgrey;
    height: 70px;
    width: 140px;
    object-fit: cover;
}

.fav-item-video i {
    position: absolute;
    left: 68px;
    right: 0;
    width: 10px;
    margin-right: auto;
}

.fav-item-audio {
    margin: 0 10px;
}

.fav-item-audio audio {
    outline: none;
    filter: sepia(20%) saturate(70%) grayscale(1) contrast(99%) invert(12%);
}

.fav-item-sender-time {
    max-width: 120px;
    text-align: right;
}

.fav-item-sender-time .time {
    font-size: 12px;
    color: #b6b6b6;
}

.fav-item-sender-time .sender {
    font-size: 12px;
    color: #b2b2b2;
    padding-top: 3px;
}

.media-category-container {
    display: flex;
    flex-direction: column;
    padding: 0 80px;
}

.media-category-container p {
    font-size: 14px;
    padding: 20px 0 10px 0;
}

.media-category-items {
    width: 100%;
    display: flex;
    align-items: flex-start;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: flex-start;
}

.media-item-image img {
    width: 70px;
    height: 70px;
    object-fit: cover;
    padding: 2px;
}

.media-item-video {
    position: relative;
}

.media-item-video video {
    width: 70px;
    height: 70px;
    object-fit: cover;
    padding: 2px;
}

.media-item-video i {
    position: absolute;
    top: 32px;
    left: 32px;
    width: 10px;
    margin-right: auto;
}

</style>
